/* ----------------------------------------------------------------------
*
* Copyright (C) 2025 XiaoFei. All rights reserved.
*
* @file:		TaoJingChi_HMI.c
* @author:		XiaoFei
* @Date:     	13-March-2025
* @Revision: 	V1
* @Project: 	XiaoFei BSP Library
*
* -------------------------------------------------------------------- */

#include "stm32f10x.h"
#include "TaoJingChi_HMI.h"
#include "XiaoFei_Delay.h"
#include "stdio.h"
#include "stdarg.h"
#include "stdlib.h"

HMI_BufDef HMI_BufThis;

/* 
* @function: 	HMI_BufInit
* @parameter:	[in] HMI_Buf				The handle of HMI.
* @parameter:	[in] len				    The max length of HMI data.
*/
static void HMI_BufInit(HMI_BufDef* HMI_Buf, unsigned int len)
{
    HMI_Buf->buf = (unsigned char*)malloc(len * sizeof(unsigned char));
    HMI_Buf->len_max = len;
    HMI_Buf->len = 0;
}

/* 
* @function: 	HMI_BufClear
* @parameter:	[in] HMI_Buf				The handle of HMI.
* @parameter:	[in] ClThis				    Input 0x01 to clear all buffers, otherwise input 0x00.
*/
void HMI_BufClear(HMI_BufDef* HMI_Buf, unsigned char ClThis)
{
    HMI_Buf->len = 0;
    for (unsigned int i = 0; i < HMI_Buf->len_max; i++)
        HMI_Buf->buf[i] = 0;
    if (!(!ClThis))
    {
        HMI_BufThis.len = 0;
        for (unsigned int i = 0; i < HMI_BufThis.len_max; i++)
            HMI_BufThis.buf[i] = 0;
    }
}

/* 
* @function: 	HMI_BufGet
* @parameter:	[in] HMI_Buf				The handle of HMI.
* @parameter:	[in] us				        The interval for obtaining two adjacent pointers.
* @return:		Return 0x01 if the data has get successful, otherwise return 0x00.
*/
unsigned char HMI_BufGet(HMI_BufDef* HMI_Buf, unsigned int us)
{
    unsigned int len = HMI_BufThis.len;
    XiaoFei_Delay_us(us);
    if ((len == HMI_BufThis.len) && (HMI_BufThis.len != 0))
    {
        HMI_Buf->len = HMI_BufThis.len;
        HMI_Buf->len_max = HMI_BufThis.len_max;
        for (unsigned int i = 0; i < HMI_Buf->len_max; i++)
            HMI_Buf->buf[i] = HMI_BufThis.buf[i];
        return 0x01;
    }
    return 0x00;
}

/* 
* @function: 	HMI_Init
* @parameter:	[out] HMI_Buf				The handle of HMI.
* @parameter:	[in] len				    The max length of HMI data.
*/
void HMI_Init(HMI_BufDef* HMI_Buf, unsigned int len)
{
    HMI_RCC_Usart(1);
    HMI_RCC_TX(1);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = HMI_Pin_TX;
    GPIO_Init(HMI_GPIO_TX, &GPIO_InitStructure);
    #ifdef HMI_AddRX
        HMI_RCC_RX(1);
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_InitStructure.GPIO_Pin = HMI_Pin_RX;
        GPIO_Init(HMI_GPIO_RX, &GPIO_InitStructure);
    #endif
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = HMI_BaudRate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    #ifdef HMI_AddRX
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    #else
        USART_InitStructure.USART_Mode = USART_Mode_Tx;
    #endif
    USART_Init(HMI_Usart, &USART_InitStructure);
    #ifdef HMI_AddRX
        USART_ITConfig(HMI_Usart, USART_IT_RXNE, ENABLE);
        NVIC_PriorityGroupConfig(HMI_Group);
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = HMI_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = HMI_ITPre;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = HMI_ITSub;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    #endif
    USART_Cmd(HMI_Usart, ENABLE);
    HMI_BufInit(&HMI_BufThis, len);
    HMI_BufInit(HMI_Buf, len);
    HMI_BufClear(HMI_Buf, 0x01);
}

/* 
* @function: 	HMI_SendString
* @parameter:	[in] data					 The data will be send to HMI.
*/
void HMI_SendString(char* data)
{
    for (unsigned int i = 0; data[i] != '\0'; i++)
    {
        USART_SendData(HMI_Usart, data[i]);
        while (USART_GetFlagStatus(HMI_Usart, USART_FLAG_TXE) == RESET);
    }
}

/* 
* @function: 	HMI_Printf
* @parameter:	[in] format					 The parameter will be send to HMI.
*/
void HMI_Printf(char* format, ...)
{
    char String[100];
    va_list arg;
    va_start(arg, format);
    vsprintf(String, format, arg);
    va_end(arg);
    HMI_SendString(String);
}

#ifdef HMI_AddRX
/* 
* @function: 	HMI_IRQHandler
* @callback:	The function will be callback when get the data from HMI.
*/
void HMI_IRQHandler(void)
{
    if (USART_GetFlagStatus(HMI_Usart, USART_FLAG_RXNE) == SET)
    {
        USART_ClearITPendingBit(HMI_Usart, USART_IT_RXNE);
        HMI_BufThis.buf[HMI_BufThis.len] = USART_ReceiveData(HMI_Usart);
        if (HMI_BufThis.len < HMI_BufThis.len_max)
            HMI_BufThis.len++;
    }
}
#endif


